package com.aop;


import com.domain.sys.SysLog;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.service.SysLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Aspect
@Component
@Slf4j
public class SysLogAspect {
    private Object obj;

    //定义一个切入点
    @Pointcut("@annotation(MyAspect)")
    public void test(){

    }

    /**
     * @Around  可以在目标方法之前或之后做功能扩展
     * @param joinPoint 封装了目标方法的一个对象
     * @return 目标方法执行结果
     * @throws Throwable
     */
    @Around("test()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            long t1 = System.currentTimeMillis();
            Object obj = joinPoint.proceed();//调用目标方法
            long t2 = System.currentTimeMillis();

            this.saveLog(joinPoint, t2 - t1);
            return obj;

        }catch (Exception e){
            this.errorLog(joinPoint,e.getMessage());
            throw e;
        }

    }

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    private IPUtils ipUtils;

    private void saveLog(ProceedingJoinPoint point,long time) throws NoSuchMethodException, JsonProcessingException {


        //获取目标方法   方法名 参数列表
        Class clazz = point.getTarget().getClass();
        //获得方法名、参数类型
        MethodSignature s = (MethodSignature)point.getSignature();
        Method m = clazz.getDeclaredMethod(s.getName(),s.getParameterTypes());
        MyAspect myAspect = m.getAnnotation(MyAspect.class);



        SysLog sysLog = new SysLog();
        sysLog.setUsername("cgb");
        sysLog.setIp(ipUtils.getIpAddr());
        sysLog.setOperation(myAspect.value());
        sysLog.setMethod(clazz.getName() + "." + m.getName());
        sysLog.setParams(new ObjectMapper().writeValueAsString(point.getArgs()));
        sysLog.setTime(time);
        sysLog.setCreatedTime(new Date());

        new Thread(){
            @Override
            public void run() {
                sysLogService.saveObject(sysLog);
            }
        }.start();

    }

    private void errorLog(ProceedingJoinPoint point, String exceptionMsg ) throws JsonProcessingException {
        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();
        String params = new ObjectMapper().writeValueAsString(point.getArgs());
        log.error(className + "." + methodName + params + exceptionMsg);
    }



}
